import { Rule } from "antd/es/form";
import { FormInstance } from "antd";

// 微信规则值的类型定义
export interface WxRuleValue {
	[key: string]: any;
}

// 微信规则的结构：字段名为键，规则对象为值
export interface WxRules {
	[field: string]: WxRuleValue;
}

// 微信规则的自定义消息
export interface WxMessages {
	[field: string]: {
		[rule: string]: string;
	};
}

// 转换函数
export const convertWxValidateToAntdRules = (
	wxRules: WxRules,
	wxMessages: WxMessages = {},
	formInstance?: FormInstance
): Record<string, Rule[]> => {
	// 内置规则验证方法
	const methods: Record<string, (value: any, param?: any) => boolean> = {
		required: value => {
			if (typeof value === "number") return true;
			if (typeof value === "boolean") return true;
			return value !== undefined && value !== null && value !== "";
		},
		email: value => {
			return (
				!value ||
				/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(
					value
				)
			);
		},
		tel: value => {
			return !value || /^(13[0-9]|14[0-9]|15[0-9]|16[0-9]|17[0-9]|18[0-9]|19[0-9])\d{8}$/.test(value);
		},
		url: value => {
			return (
				!value ||
				/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(
					value
				)
			);
		},
		date: value => {
			return !value || !/Invalid|NaN/.test(new Date(value).toString());
		},
		dateISO: value => {
			return !value || /^\d{4}[/-](0?[1-9]|1[012])[/-](0?[1-9]|[12][0-9]|3[01])$/.test(value);
		},
		number: value => {
			return !value || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value);
		},
		digits: value => {
			return !value || /^\d+$/.test(value);
		},
		idcard: value => {
			return !value || /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value);
		},
		creditCode: value => {
			return !value || /^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/i.test(value);
		},
		equalTo: (value, param) => {
			return !value || value === param;
		},
		contains: (value, param) => {
			return !value || value.includes(param);
		},
		minlength: (value, param) => {
			return !value || (typeof value === "string" && value.length >= param);
		},
		maxlength: (value, param) => {
			return !value || (typeof value === "string" && value.length <= param);
		},
		rangelength: (value, param) => {
			return !value || (typeof value === "string" && value.length >= param[0] && value.length <= param[1]);
		},
		min: (value, param) => {
			return !value || (typeof value === "number" && value >= param);
		},
		max: (value, param) => {
			return !value || (typeof value === "number" && value <= param);
		},
		range: (value, param) => {
			return !value || (typeof value === "number" && value >= param[0] && value <= param[1]);
		},
		greaterthan: (value, param) => {
			return !value || (typeof value === "number" && value > param);
		}
	};

	// 默认错误消息
	const defaultMessages: Record<string, string> = {
		required: "这是必填字段。",
		email: "请输入有效的电子邮件地址。",
		tel: "请输入正确的手机号码。",
		url: "请输入有效的网址。",
		date: "请输入有效的日期。",
		dateISO: "请输入有效的日期（ISO），例如：2009-06-23，1998/01/22。",
		number: "请输入有效的数字。",
		digits: "只能输入数字。",
		idcard: "请输入18位的有效身份证。",
		creditCode: "请输入正确的统一社会信用代码。",
		equalTo: "输入值必须和 {0} 相同。",
		contains: "输入值必须包含 {0}。",
		minlength: "最少要输入 {0} 个字符。",
		maxlength: "最多可以输入 {0} 个字符。",
		rangelength: "请输入长度在 {0} 到 {1} 之间的字符。",
		min: "请输入不小于 {0} 的数值。",
		max: "请输入不大于 {0} 的数值。",
		range: "请输入范围在 {0} 到 {1} 之间的数值。",
		greaterthan: "请输入大于 {0} 的数值。"
	};

	const antdRules: Record<string, Rule[]> = {};

	// 遍历WxRules对象中的每个字段
	Object.entries(wxRules).forEach(([field, rules]) => {
		antdRules[field] = [];

		// 遍历每个字段的规则
		Object.entries(rules).forEach(([ruleName, ruleParam]) => {
			// 获取错误消息
			let message = wxMessages[field]?.[ruleName] || defaultMessages[ruleName] || "验证失败";

			// 处理消息中的占位符
			if (Array.isArray(ruleParam)) {
				message = message.replace(/\{(\d+)\}/g, (match, index) => {
					return ruleParam[index] !== undefined ? ruleParam[index] : match;
				});
			} else if (typeof ruleParam === "object" && ruleParam !== null) {
				message = message.replace(/\{(\d+)\}/g, (match, index) => {
					const key = Object.keys(ruleParam)[index];
					return key !== undefined ? ruleParam[key] : match;
				});
			} else if (ruleParam !== undefined && ruleParam !== null) {
				message = message.replace("{0}", ruleParam);
			}

			// 创建规则对象
			const createRule = (): Rule | null => {
				// 必需规则
				if (ruleName === "required") {
					return {
						required: true,
						message
					};
				}

				// 使用自定义验证器
				if (methods[ruleName]) {
					// 针对 equalTo 规则的特殊处理
					if (ruleName === "equalTo") {
						const targetField = ruleParam as string;

						return {
							validator: async (_, value) => {
								try {
									if (!value) return Promise.resolve();

									let targetValue;

									// 优先尝试使用传入的表单实例
									if (formInstance && formInstance.getFieldValue) {
										targetValue = formInstance.getFieldValue(targetField);
									}
									// 如果无法获取目标值，使用全局值
									else if (wxRules[targetField]?.defaultValue) {
										targetValue = wxRules[targetField].defaultValue;
									}
									// 如果所有方式都失败，使用规则参数作为值
									else {
										targetValue = ruleParam;
									}

									return methods.equalTo(value, targetValue) ? Promise.resolve() : Promise.reject(new Error(message));
								} catch (error) {
									return Promise.reject(new Error("无法获取目标字段值"));
								}
							}
						};
					}

					// 处理其他自定义验证方法
					return {
						validator: (_, value) => {
							if (!value && value !== 0) return Promise.resolve();
							return methods[ruleName](value, ruleParam) ? Promise.resolve() : Promise.reject(new Error(message));
						}
					};
				}

				// 处理特定规则类型
				switch (ruleName) {
					case "minlength":
						return {
							min: ruleParam as number,
							message
						};

					case "maxlength":
						return {
							max: ruleParam as number,
							message
						};

					case "rangelength":
						return {
							min: ruleParam[0],
							max: ruleParam[1],
							message
						};

					case "min":
						return {
							type: "number" as any,
							min: ruleParam as number,
							message
						};

					case "max":
						return {
							type: "number" as any,
							max: ruleParam as number,
							message
						};

					case "range":
						return {
							type: "number" as any,
							min: ruleParam[0],
							max: ruleParam[1],
							message
						};

					default:
						return {
							message: `不支持规则类型: ${ruleName}`
						};
				}
			};

			const rule = createRule();
			if (rule) {
				antdRules[field].push(rule);
			}
		});
	});

	return antdRules;
};

/**
 * 创建自定义的 equalTo 规则处理函数（推荐使用）
 *
 * @param targetField 要比较的目标字段名
 * @param message 错误提示信息
 * @param formInstance 表单实例（可选）
 * @param wxRules 微信规则对象（可选）
 * @returns Ant Design 规则对象
 */
export const createEqualToRule = (
	targetField: string,
	message: string,
	formInstance?: FormInstance,
	wxRules?: WxRules
): Rule => ({
	validator: async (_, value) => {
		try {
			if (!value) return Promise.resolve();

			let targetValue;

			// 优先尝试使用传入的表单实例
			if (formInstance && formInstance.getFieldValue) {
				targetValue = formInstance.getFieldValue(targetField);
			}
			// 如果无法获取目标值，检查是否有全局值
			else if (wxRules?.[targetField]?.defaultValue) {
				targetValue = wxRules[targetField].defaultValue;
			}
			// 如果所有方式都失败，抛出错误
			else {
				return Promise.reject(new Error(`无法获取目标字段 ${targetField} 的值`));
			}

			return value === targetValue ? Promise.resolve() : Promise.reject(new Error(message));
		} catch (error) {
			return Promise.reject(new Error("字段比较失败"));
		}
	}
});
// 使用示例
// 示例：微信小程序中的规则定义
// const wxRules: WxRules = {
// 	username: { required: true, minlength: 3 },
// 	email: { required: true, email: true },
// 	phone: { tel: true },
// 	password: { required: true, minlength: 6 },
// 	confirmPassword: { required: true, equalTo: "password" },
// 	age: { required: true, min: 18, max: 100 },
// 	website: { url: true },
// 	idCard: { idcard: true },
// 	companyCode: { creditCode: true },
// 	about: { maxlength: 200 },
// 	discount: { range: [5, 30] },
// 	score: { greaterthan: 60 }
// };

// // 示例：自定义错误消息
// const wxMessages: WxMessages = {
// 	username: {
// 		required: "请输入用户名",
// 		minlength: "用户名至少需要3个字符"
// 	},
// 	email: {
// 		required: "请输入邮箱地址",
// 		email: "请输入有效的邮箱格式"
// 	},
// 	confirmPassword: {
// 		required: "请确认密码",
// 		equalTo: "两次输入的密码不一致"
// 	},
// 	age: {
// 		required: "请输入年龄",
// 		min: "年龄必须大于或等于18岁",
// 		max: "年龄必须小于或等于100岁"
// 	},
// 	discount: {
// 		range: "折扣必须在5到30之间"
// 	}
// };

// // 转换为Antd规则
// const antdRules = convertWxValidateToAntdRules(wxRules, wxMessages);

// 需要校验不同值情况下传入form
// const antdRules = convertWxValidateToAntdRules(wxRules, wxMessages, form);

// // 添加自定义的多个equalTo规则,不需要规则里定义 equalTo，将手动添加
// antdRules.confirmPassword.push(
//   createEqualToRule('password', '两次输入的密码不一致', form, wxRules)
// );

// antdRules.confirmEmail.push(
//   createEqualToRule('alternativeEmail', '两次输入的邮箱地址不一致', form, wxRules)
// );
